﻿using BCCommon;
using BCData.Sim.Admin.AdminPermissionConfig;
using BCData.Sim.Admin.AdminPermissionMappingPage;
using BCData.Sim.Admin.AdminPermissionRecord;
using BCDto.Sim.Admin.AdminPermissionConfig;
using BCDto.Common.TreeNode;
using BCEntity;
using BCEntity.Sim.Admin.AdminPermissionConfig;
using BCService.Utils;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BCEntity.Common.EntityNameConst;

namespace BCService.Sim.Admin.AdminPermissionConfig
{
    public class AdminPermissionConfigService : IAdminPermissionConfigService
    {
        private readonly IAdminPermissionConfigData adminPermissionConfigData;
        private readonly IAdminPermissionMappingPageData adminPermissionMappingPageData;
        private readonly IAdminPermissionRecordData adminPermissionRecordData;
        private readonly IRedisService redisService;
        private readonly string key = string.Format("{0}", EntityNameConst.AdminPermissionConfigEntity);

        
        public AdminPermissionConfigService(IAdminPermissionConfigData adminPermissionConfigData, IAdminPermissionMappingPageData adminPermissionMappingPageData, IAdminPermissionRecordData adminPermissionRecordData, IRedisService redisService)
        {
            this.adminPermissionConfigData = adminPermissionConfigData;
            this.adminPermissionMappingPageData = adminPermissionMappingPageData;
            this.adminPermissionRecordData = adminPermissionRecordData;
            this.redisService = redisService;
        }

        public AdminPermissionConfigDto Add(AdminPermissionConfigRequestDto requestDto)
        {
            if (this.adminPermissionConfigData.CheckExists(requestDto.PermissionCode).GetAwaiter().GetResult())
            {
                throw new ArgumentException("此权限码已存在");
            }
            if (string.IsNullOrWhiteSpace(requestDto.PermissionName.Trim()))
            {
                throw new ArgumentException("此权限名称为必填项");
            }
            if (string.IsNullOrWhiteSpace(requestDto.PermissionCode.Trim()))
            {
                throw new ArgumentException("此权限码为必填项");
            }
            if (string.IsNullOrWhiteSpace(requestDto.PermissionPathCode.Trim()))
            {
                throw new ArgumentException("此权限路径码不能为空");
            }
           
            int level = 0;
            if (requestDto.PermissionPathCode.IndexOf(".") > -1)
            {
                level = requestDto.PermissionPathCode.Split(".").Length-1;
            }
            var entity = requestDto.As<AdminPermissionConfigEntity>();
            entity.PermissionLevel = level;
            var result = this.adminPermissionConfigData.Add(entity).GetAwaiter().GetResult().As<AdminPermissionConfigDto>();
            if (result != null)
            {
                this.redisService.DeleteAsync(key);
            }
            return result;
        }

        public AdminPermissionConfigDto Update(AdminPermissionConfigPutDto putDto)
        {
            if (!this.adminPermissionConfigData.CheckExists(putDto.AdminPermissionConfigId).GetAwaiter().GetResult())
            {
                throw new ArgumentException("此权限配置不存在");
            }
            if (string.IsNullOrWhiteSpace(putDto.PermissionName.Trim()))
            {
                throw new ArgumentException("此权限名称为必填项");
            }
            if (string.IsNullOrWhiteSpace(putDto.PermissionCode.Trim()))
            {
                throw new ArgumentException("此权限码为必填项");
            }
            if (string.IsNullOrWhiteSpace(putDto.PermissionPathCode.Trim()))
            {
                throw new ArgumentException("此权限路径码不能为空");
            }
            var oldEntity = this.adminPermissionConfigData.GetEntity(putDto.AdminPermissionConfigId).GetAwaiter().GetResult();
            if (oldEntity.PermissionCode.ToLower() != putDto.PermissionCode.ToLower())
            {
                if (this.adminPermissionConfigData.CheckExists(putDto.PermissionCode).GetAwaiter().GetResult())
                {
                    throw new ArgumentException("此权限编码已存在");
                }
            }
            int level = 0;
            if (putDto.PermissionPathCode.IndexOf(".") > -1)
            {
                level = putDto.PermissionPathCode.Split(".").Length-1;
            }
            var entity = putDto.As<AdminPermissionConfigEntity>();
            entity.PermissionLevel = level;
            var mappingEntities = this.adminPermissionMappingPageData.GetList(oldEntity.PermissionCode).GetAwaiter().GetResult();
            var recordEntities = this.adminPermissionRecordData.GetList(oldEntity.PermissionCode).GetAwaiter().GetResult();

            var result = this.adminPermissionConfigData.Update(entity, mappingEntities.Select(p=>p.AdminPermissionMappingPageId).ToList(),recordEntities.Select(p=>p.AdminPermissionRecordId).ToList()).GetAwaiter().GetResult();
            if (result)
            {
                string mappingKey = string.Format("{0}", EntityNameConst.AdminPermissionMappingPageViewDto);
                string departmentKey = string.Format("{0}", EntityNameConst.DepartmentPermissionListEntity);
                string adminRecordKey = string.Format("{0}", EntityNameConst.AdminPermissionRecordListEntity);
                this.redisService.DeleteMultipleKey(key, false);
                this.redisService.DeleteMultipleKey(mappingKey, false);
                this.redisService.DeleteMultipleKey(departmentKey, false);
                this.redisService.DeleteMultipleKey(adminRecordKey, false);
            }

            return entity.As<AdminPermissionConfigDto>();
        }

        public bool CheckExists(string permissionCode)
        {
            return this.adminPermissionConfigData.CheckExists(permissionCode.Trim()).GetAwaiter().GetResult();
        }

        public void Delete(long adminPermissionConfigId)
        {
            var entity = this.adminPermissionConfigData.GetEntity(adminPermissionConfigId).GetAwaiter().GetResult();
            if (this.adminPermissionMappingPageData.CheckPermissionCodeExists(entity.PermissionCode).GetAwaiter().GetResult())
            {
                throw new ArgumentException("此权限码已被页面映射，请先移除页面映射");
            }
            this.adminPermissionConfigData.Delete(adminPermissionConfigId);
            this.redisService.DeleteAsync(key);
        }

        public IEnumerable<AdminPermissionConfigDto> GetList()
        {
            var result = this.redisService.TryGet(key, () => this.adminPermissionConfigData.GetList().GetAwaiter().GetResult(), new TimeSpan(1, 0, 0, 0, 0));
            return result.As<IEnumerable<AdminPermissionConfigDto>>();
        }
        
        public IEnumerable<TreeNodeDto<AdminPermissionConfigDto>> GetUnusedList()
        {
            var data = this.adminPermissionConfigData.GetUnusedList().GetAwaiter().GetResult();
            List<TreeNodeDto<AdminPermissionConfigDto>> list = new List<TreeNodeDto<AdminPermissionConfigDto>>();

            var dataRoot = data.Where(p => p.PermissionPathCode.IndexOf(".") == -1);
            foreach(var item in dataRoot)
            {
                TreeNodeDto<AdminPermissionConfigDto> nodeDto = new TreeNodeDto<AdminPermissionConfigDto>
                {
                    Title = item.PermissionName + "：(" + item.PermissionPathCode + ")--" + item.PermissionCode,
                    Value = item.PermissionPathCode,
                    Key = item.PermissionCode,
                    Disabled = item.Disabled,
                    SourceData = item.As<AdminPermissionConfigDto>()
                };
                nodeDto.Children = GetChildrenNode(data, nodeDto);
                if (nodeDto.Children.Any()) {
                    nodeDto.Expanded = true;
                }
                else
                {
                    nodeDto.IsLeaf = true;
                    nodeDto.Children = null;
                }
                list.Add(nodeDto);
            }

            return list;
        }

        private List<TreeNodeDto<AdminPermissionConfigDto>> GetChildrenNode(IEnumerable<AdminPermissionConfigEntity> sourceData,TreeNodeDto<AdminPermissionConfigDto> treeNodeDto)
        {
            List<TreeNodeDto<AdminPermissionConfigDto>> list = new List<TreeNodeDto<AdminPermissionConfigDto>>();
            string permissionCode = treeNodeDto.Key.ToString();
            string permissionPathCode = treeNodeDto.Value.ToString();
            int length = permissionPathCode.Length;
            List<AdminPermissionConfigEntity> dataChildren = new List<AdminPermissionConfigEntity>();
            foreach(var data in sourceData)
            {
                if (data.PermissionPathCode.Length >= length)
                {
                    if (data.PermissionPathCode.Substring(0, length).Equals(permissionPathCode) && data.PermissionCode != permissionCode)
                    {
                        dataChildren.Add(data);
                    }
                }
            }
            foreach (var item in dataChildren)
            {
                if (item.PermissionPathCode.Replace(permissionPathCode, "").Split('.').Length==2)
                {
                    TreeNodeDto<AdminPermissionConfigDto> nodeDto = new TreeNodeDto<AdminPermissionConfigDto>
                    {
                        Title = item.PermissionName + "：(" + item.PermissionPathCode + ")--" + item.PermissionCode,
                        Value = item.PermissionPathCode,
                        Key = item.PermissionCode,
                        Disabled = item.Disabled,
                        SourceData = item.As<AdminPermissionConfigDto>()
                    };
                    nodeDto.Children = GetChildrenNode(dataChildren, nodeDto);
                    if (nodeDto.Children.Any())
                    {
                        nodeDto.Expanded = true;
                    }
                    else
                    {
                        nodeDto.IsLeaf = true;
                        nodeDto.Children = null;
                    }
                    list.Add(nodeDto);
                }
            }
            return list;
        }

        public PageableList<AdminPermissionConfigDto> Query(string permissionName, string permissionCode, string permissionPathCode,string sortName,bool? ascending, int pageIndex, int pageSize)
        {
            var queryResult = this.adminPermissionConfigData.Query(permissionName,permissionCode, permissionPathCode, sortName, ascending, pageIndex, pageSize).GetAwaiter().GetResult();
            return new PageableList<AdminPermissionConfigDto>
            {
                Count = queryResult.Item2,
                Items = queryResult.Item1.As<IEnumerable<AdminPermissionConfigDto>>(),
                ServerTime = DateTime.Now,
                PageIndex = pageIndex,
                PageSize = pageSize
            };
        }

        public void FixErrorPermissionConfigRecord()
        {
            var list = this.adminPermissionConfigData.GetList().GetAwaiter().GetResult();

            foreach (var entity in list)
            {
                string[] path = entity.PermissionPathCode.Split(".");
                StringBuilder sb = new StringBuilder();
                for (int i = 0; i < path.Length; i++)
                {
                    List<string> words = EnglishWordUtils.EnglishWordDismantling(path[i]);
                    if (i == path.Length - 1)
                    {
                        foreach (string word in words)
                        {
                            sb.Append(word.Substring(0, 1).ToUpper());
                            sb.Append(word.Substring(1));
                        }
                    }
                    else
                    {

                        foreach (string word in words)
                        {
                            sb.Append(word.Substring(0, 1).ToUpper());
                        }

                        sb.Append("_");
                    }
                }
                AdminPermissionConfigPutDto putDto = new AdminPermissionConfigPutDto
                {
                    AdminPermissionConfigId = entity.AdminPermissionConfigId,
                    PermissionName = entity.PermissionName,
                    PermissionCode = sb.ToString(),
                    PermissionPathCode = entity.PermissionPathCode
                };
                this.Update(putDto);
            }
        }
    }
}
